const httpStatus = require('http-status');
const tokenService = require('./token.service');
const userService = require('./user.service');
const { Token } = require('../models');
const ApiError = require('../utils/ApiError');
const { tokenTypes } = require('../config/tokens');
const axios = require('axios');
const config = require('../config/config');
const jwt = require('jsonwebtoken');

/**
 * 用户登录
 * @param {string} email - 邮箱
 * @param {string} password - 密码
 * @returns {Promise<User>}
 */
const login = async (email, password) => {
  const user = await userService.getUserByEmail(email);
  if (!user || !(await user.isPasswordMatch(password))) {
    throw new ApiError(httpStatus.UNAUTHORIZED, '邮箱或密码不正确');
  }
  return user;
};

/**
 * 用户登出
 * @param {string} refreshToken - 刷新令牌
 * @returns {Promise}
 */
const logout = async (refreshToken) => {
  const refreshTokenDoc = await Token.findOne({ token: refreshToken, type: tokenTypes.REFRESH, blacklisted: false });
  if (!refreshTokenDoc) {
    throw new ApiError(httpStatus.NOT_FOUND, '找不到Token');
  }
  await Token.findByIdAndUpdate(refreshTokenDoc._id, { blacklisted: true });
};

/**
 * 刷新Auth Tokens
 * @param {string} refreshToken - 刷新令牌
 * @returns {Promise<Object>}
 */
const refreshAuth = async (refreshToken) => {
  try {
    // 解码refreshToken，但不做验证，以获取payload中的用户类型
    const decoded = jwt.decode(refreshToken);
    if (!decoded) {
      throw new ApiError(httpStatus.UNAUTHORIZED, '无效的刷新令牌');
    }
    
    console.log('刷新令牌解码结果:', { 
      userType: decoded.userType, 
      sub: decoded.sub.substring(0, 8) + '...',
      tokenType: decoded.type
    });
    
    // 验证刷新令牌
    const refreshTokenDoc = await tokenService.verifyToken(refreshToken, tokenTypes.REFRESH);
    
    // 根据用户类型查询用户
    let user;
    if (decoded.userType === 'admin') {
      const Admin = require('../models/admin.model');
      user = await Admin.findById(refreshTokenDoc.user);
      if (!user) {
        throw new ApiError(httpStatus.UNAUTHORIZED, '管理员不存在或已被删除');
      }
    } else {
      user = await userService.getUserById(refreshTokenDoc.user);
      if (!user) {
        throw new ApiError(httpStatus.UNAUTHORIZED, '用户不存在或已被删除');
      }
    }
    
    // 删除旧的刷新令牌
    await Token.findByIdAndDelete(refreshTokenDoc.id);
    
    // 生成新的令牌，根据用户类型指定正确的参数
    return tokenService.generateAuthTokens(user, decoded.userType || 'user');
  } catch (error) {
    if (error instanceof ApiError) {
      throw error;
    }
    console.error('刷新令牌错误:', error);
    throw new ApiError(httpStatus.UNAUTHORIZED, '刷新令牌失败，请重新登录');
  }
};

/**
 * 重置密码
 * @param {string} resetPasswordToken - 重置密码令牌
 * @param {string} newPassword - 新密码
 * @returns {Promise}
 */
const resetPassword = async (resetPasswordToken, newPassword) => {
  try {
    const resetPasswordTokenDoc = await tokenService.verifyToken(resetPasswordToken, tokenTypes.RESET_PASSWORD);
    const user = await userService.getUserById(resetPasswordTokenDoc.user);
    if (!user) {
      throw new Error();
    }
    await userService.updateUserById(user.id, { password: newPassword });
    await Token.deleteMany({ user: user.id, type: tokenTypes.RESET_PASSWORD });
  } catch (error) {
    throw new ApiError(httpStatus.UNAUTHORIZED, '密码重置失败');
  }
};

/**
 * 验证邮箱
 * @param {string} verifyEmailToken - 验证邮箱令牌
 * @returns {Promise}
 */
const verifyEmail = async (verifyEmailToken) => {
  try {
    const verifyEmailTokenDoc = await tokenService.verifyToken(verifyEmailToken, tokenTypes.VERIFY_EMAIL);
    const user = await userService.getUserById(verifyEmailTokenDoc.user);
    if (!user) {
      throw new Error();
    }
    await Token.deleteMany({ user: user.id, type: tokenTypes.VERIFY_EMAIL });
    await userService.updateUserById(user.id, { isEmailVerified: true });
  } catch (error) {
    throw new ApiError(httpStatus.UNAUTHORIZED, '邮箱验证失败');
  }
};

/**
 * 使用微信临时登录凭证进行登录
 * @param {string} code - 微信临时登录凭证
 * @returns {Promise<Object>} 用户信息和登录状态
 */
const loginWithWechat = async (code) => {
  try {
    // 从配置文件中获取微信小程序配置
    const appId = config.wechat.appId;
    const appSecret = config.wechat.appSecret;
    
    console.log('使用微信配置:', { appId, appSecret: appSecret.substring(0, 4) + '******' });
    
    // 请求微信API获取openid和session_key
    const response = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
      params: {
        appid: appId,
        secret: appSecret,
        js_code: code,
        grant_type: 'authorization_code'
      }
    });
    
    if (response.data.errcode) {
      throw new ApiError(httpStatus.BAD_REQUEST, `微信登录失败: ${response.data.errmsg}`);
    }
    
    const { openid, session_key } = response.data;
    
    // 根据openid查找用户
    let user = await userService.getUserByWechatOpenid(openid);
    let isNewUser = false;
    
    // 如果用户不存在，创建新用户
    if (!user) {
      isNewUser = true;
      user = await userService.createUser({
        wechatOpenid: openid,
        nickname: `用户${openid.substring(0, 6)}`,
        avatar: '', // 可以设置默认头像
        role: 'user',
      });
    }
    
    return {
      user,
      isNewUser
    };
  } catch (error) {
    // 如果是API错误直接抛出
    if (error instanceof ApiError) {
      throw error;
    }
    console.error('微信登录错误:', error);
    throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, '微信登录处理失败');
  }
};

module.exports = {
  login,
  logout,
  refreshAuth,
  resetPassword,
  verifyEmail,
  loginWithWechat,
}; 